//
//  NSObject+Runtime.m
//  OMTCoreKit
//
//  Created by 昭荣伊 on 2018/7/27.
//

#import "NSObject+Runtime.h"
#import <objc/runtime.h>

@implementation NSObject (Runtime)

+ (BOOL)omt_swizzleInstanceMethod:(SEL)originalSel targetSel:(SEL)targetSel {
    
    return [self omt_swizzleInstanceMethod:[self class] originalSel:originalSel targetClass:[self class] targetSel:targetSel];
}

+ (BOOL)omt_swizzleInstanceMethod:(SEL)originalSel targetClass:(Class)targetClass targetSel:(SEL)targetSel {
    if (!originalSel || !targetClass || !targetSel) {
        return NO;
    }
    return [self omt_swizzleInstanceMethod:[self class] originalSel:originalSel targetClass:targetClass targetSel:targetSel];
}

+ (BOOL)omt_swizzleInstanceMethod:(Class)originalClass originalSel:(SEL)originalSel targetClass:(Class)targetClass targetSel:(SEL)targetSel {
    if (!originalClass || !originalSel || !targetClass || !targetSel) {
        return NO;
    }
    Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
    Method newMethod = class_getInstanceMethod(targetClass, targetSel);
    if (!originalMethod || !newMethod) return NO;
    
    class_addMethod(originalClass,
                    originalSel,
                    class_getMethodImplementation(originalClass, originalSel),
                    method_getTypeEncoding(originalMethod));
    class_addMethod(targetClass,
                    targetSel,
                    class_getMethodImplementation(targetClass, targetSel),
                    method_getTypeEncoding(newMethod));
    
    method_exchangeImplementations(class_getInstanceMethod(originalClass, originalSel),
                                   class_getInstanceMethod(targetClass, targetSel));
    
    return YES;
}

+ (BOOL)omt_swizzleClassMethod:(SEL)originalSel targetSel:(SEL)targetSel {
    
    return [self omt_swizzleClassMethod:[self class] originalSel:originalSel targetClass:[self class] targetSel:targetSel];
}

+ (BOOL)omt_swizzleClassMethod:(SEL)originalSel targetClass:(Class)targetClass targetSel:(SEL)targetSel {
    
    return [self omt_swizzleClassMethod:[self class] originalSel:originalSel targetClass:targetClass targetSel:targetSel];
}

+ (BOOL)omt_swizzleClassMethod:(Class)originalClass originalSel:(SEL)originalSel targetClass:(Class)targetClass targetSel:(SEL)targetSel {
    if (!originalClass || !originalSel || !targetClass || !targetSel) {
        return NO;
    }
    Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
    Method newMethod = class_getInstanceMethod(targetClass, targetSel);
    if (!originalMethod || !newMethod) return NO;
    method_exchangeImplementations(originalMethod, newMethod);
    return YES;
}

@end
